#include "QQSql.h"

QX_REGISTER_CPP(QQUser)
QX_REGISTER_CPP(QQMessage)

namespace qx
{
	template <> void register_class(QxClass<QQUser>& t)
	{
		t.setName("user");
		IxDataMember* p = t.id(&QQUser::m_account, "account");
		p->setSqlType("VARCHAR(255)");
		p = t.data(&QQUser::m_password, "password");
		p = t.data(&QQUser::m_nickname, "nickname");
		p = t.data(&QQUser::m_icon, "icon");
		p->setDefaultValue("C:/Users/30842/Desktop/QQ_TEMP/server/QQ.png");
		p = t.data(&QQUser::m_friends, "friends");
		p->setSqlType("TEXT");
		p = t.data(&QQUser::m_token, "token");
	}

	template <> void register_class(QxClass<QQMessage>& t)
	{
		t.setName("message");
		IxDataMember* p = t.id(&QQMessage::m_id, "id");
		p->setSqlType("VARCHAR(255)");
		t.data(&QQMessage::m_sender, "sender");
		t.data(&QQMessage::m_receiver, "receiver");
		t.data(&QQMessage::m_content, "content");
		t.data(&QQMessage::m_time, "time");
	}
}

QQSql* QQSql::m_instance = nullptr;

QQSql::QQSql(QObject* parent)
	: QObject(parent)
{}

QQSql::~QQSql()
{}

QQSql* QQSql::get_instance()
{
	if (m_instance == nullptr)
	{
		m_instance = new QQSql;
	}
	return m_instance;
}

void QQSql::init()
{
	qx::QxSqlDatabase::getSingleton()->setDriverName("QMYSQL");
	qx::QxSqlDatabase::getSingleton()->setDatabaseName("QQ");
	qx::QxSqlDatabase::getSingleton()->setHostName("localhost");
	qx::QxSqlDatabase::getSingleton()->setUserName("KXJ");
	qx::QxSqlDatabase::getSingleton()->setPassword("123456");
	qx::dao::create_table<QQUser>();
	qx::dao::create_table<QQMessage>();
}

QQUser QQSql::get_user(const QString& account)
{
	QQUser user;
	user.m_account = account;
	qx::dao::fetch_by_id(user);
	return user;
}

bool QQSql::check_token(const QString& token)
{
	QQUser user;
	qx_query query;
	query.where("token").isEqualTo(token);
	qx::dao::fetch_by_query(query, user);
	return user.m_token == token;
}

bool QQSql::check_token(const QString& account, const QString& token)
{
	QQUser user;
	user.m_account = account;
	qx::dao::fetch_by_id(user);
	return user.m_token == token;
}

bool QQSql::check_token_null(const QString& account)
{
	QQUser user;
	user.m_account = account;
	qx::dao::fetch_by_id(user);
	return user.m_token.isEmpty();
}

void QQSql::update_token(const QString& account, const QString& token)
{
	QQUser user;
	user.m_account = account;
	qx::dao::fetch_by_id(user);
	user.m_token = token;
	qx::dao::update(user);
	return;
}

bool QQSql::check_user_exist(const QString& account, const QString& password)
{
	QQUser user;
	user.m_account = account;
	qx::dao::fetch_by_id(user);
	return user.m_password == password;
}

QString QQSql::register_new_user(const QString& password, const QString& nickname)
{
	QQUser user;
	QString account;
	while (true)
	{
		int firstDigit = QRandomGenerator::global()->bounded(1, 10);
		int length = QRandomGenerator::global()->bounded(4, 11);
		account = QString::number(firstDigit);
		for (int i = 0; i < length; ++i) {
			int digit = QRandomGenerator::global()->bounded(0, 10);
			account += QString::number(digit);
		}
		user.m_account = account;
		if (qx::dao::fetch_by_id(user).type() != QSqlError::NoError)
			break;
	}
	user.m_account = account;
	user.m_password = password;
	user.m_nickname = nickname;
	user.m_icon = "C:/Users/30842/Desktop/QQ_TEMP/server/QQ.png";
	user.m_friends = "";
	user.m_token = "";
	qx::dao::insert(user);
	return account;
}

bool QQSql::test_is_friend(const QString& account, const QString& friend_account)
{
	QQUser user;
	user.m_account = account;
	qx::dao::fetch_by_id(user);
	QJsonArray friends = QJsonDocument::fromJson(user.m_friends.toUtf8()).array();
	return friends.contains(friend_account);
}

void QQSql::add_friend(const QString& account, const QString& friend_account)
{
	QQUser user;
	user.m_account = account;
	qx::dao::fetch_by_id(user);
	QJsonArray friends = QJsonDocument::fromJson(user.m_friends.toUtf8()).array();
	friends.append(friend_account);
	user.m_friends = QJsonDocument(friends).toJson(QJsonDocument::Compact);
	qx::dao::update(user);

	user.m_account = friend_account;
	qx::dao::fetch_by_id(user);
	friends = QJsonDocument::fromJson(user.m_friends.toUtf8()).array();
	friends.append(account);
	user.m_friends = QJsonDocument(friends).toJson(QJsonDocument::Compact);
	qx::dao::update(user);
	return;
}

void QQSql::delete_friend(const QString& account, const QString& friend_account)
{
	QQUser user;
	user.m_account = account;
	qx::dao::fetch_by_id(user);
	QJsonArray friends = QJsonDocument::fromJson(user.m_friends.toUtf8()).array();
	for (int i = 0; i < friends.size(); ++i)
	{
		if (friends.at(i) == friend_account)
		{
			friends.removeAt(i);
			break;
		}
	}
	user.m_friends = QJsonDocument(friends).toJson(QJsonDocument::Compact);
	qx::dao::update(user);
	return;
}

void QQSql::add_message(QQMessage& message)
{
	qx::dao::insert(message);
	return;
}

void QQSql::add_message(const QString& sender, const QString& receiver, const QString& content)
{
	QQMessage message;
	message.m_sender = sender;
	message.m_receiver = receiver;
	message.m_content = content;
	message.m_time = QDateTime::currentDateTime();
	qx::dao::insert(message);
	return;
}
